package com.sofa.user.service.impl;

//import com.sofa.api.client.permission.PermissionClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sofa.api.client.permission.PermissionClient;
import com.sofa.api.dto.permission.UserRoleDTO;
import com.sofa.common.constants.*;
import com.sofa.common.Interceptors.JwtProperties;
import com.sofa.common.context.BaseContext;
import com.sofa.common.domain.PageResult;
import com.sofa.common.exception.*;
import com.sofa.common.utils.*;
import com.sofa.user.domain.dto.UserDTO;
import com.sofa.common.domain.OperationLogs;
import com.sofa.user.domain.po.User;
//import com.sofa.user.feign.PermissionServiceClient;
import com.sofa.user.domain.vo.UserVO;

import com.sofa.user.mapper.UserMapper;
import com.sofa.user.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-06-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {


    private final RabbitMqHelper rabbitMqHelper;

    private final JwtProperties jwtProperties;

    private final PermissionClient permissionClient;

    @Override
    @Transactional
    @GlobalTransactional //开启全局事务
    public Boolean register(UserDTO userDTO) {
        // 参数校验
        if(StringUtils.isBlank(userDTO.getUsername()) || StringUtils.isBlank(userDTO.getPassword())) {
            throw new CommonException("用户名和密码不能为空");
        }

        // 检查用户名是否已存在
        User user = this.lambdaQuery().select(User::getId).eq(User::getUsername, userDTO.getUsername()).one();
        if (user != null) {
            throw new CommonException("用户已存在");
        }

        // 密码加密（使用MD5）
        // 干脆不加密算了
//        userDTO.setPassword(DigestUtils.md5DigestAsHex(userDTO.getPassword().getBytes()));

        // 保存用户信息
        user = BeanUtils.copyBean(userDTO, User.class);
        save(user);
        log.info("用户注册成功: {}", user);
        try {
            // 调用权限服务，绑定默认角色
            permissionClient.bindDefaultRole(user.getId());

            // 发送操作日志
            OperationLogs logs = new OperationLogs();
            logs.setUserId(user.getId());
            logs.setAction(LogConstants.USER_REGISTER);
            logs.setIp(InetAddress.getLocalHost().getHostAddress());
            String detail = OperationLogDetailUtils.generateInsertLog(user);
            logs.setDetail("用户注册:" + detail);
            rabbitMqHelper.sendMessage(MqConstants.Exchange.SOFA_LOG_EXCHANGE, MqConstants.RoutingKey.SOFA_LOG_OPERATION, logs);
        } catch (Exception e) {
            throw new CommonException("注册过程中出现错误: " + e.getMessage());
        }
        return true;
    }

    @Override
    public UserVO login(String username, String password) {
        // 参数校验
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            throw new CommonException("用户名和密码不能为空");
        }

        // 查询用户
        User user = this.lambdaQuery()
                .eq(User::getUsername, username)
                .one();
        if (user == null) {
            throw new UserNotExitsException("用户不存在");
        }

        // 验证密码
        if(!user.getPassword().equals(password)){
            throw new PasswordErrorException("密码错误");
        }


        //登录成功后，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        log.info("{}", jwtProperties);
        String token = JwtUtil.createJWT(
                jwtProperties.getUserSecretKey(),
                jwtProperties.getUserTtl(),
                claims);

        try {
            // 发送登录日志(登录日志是不是可以不需要?)
            OperationLogs logs = new OperationLogs();
            logs.setUserId(user.getId());
            logs.setAction(LogConstants.USER_LOGIN);
            logs.setIp(InetAddress.getLocalHost().getHostAddress());
            logs.setDetail("用户" + user.getUsername() + "登录");
            rabbitMqHelper.sendMessage(MqConstants.Exchange.SOFA_LOG_EXCHANGE, MqConstants.RoutingKey.SOFA_LOG_OPERATION, logs);
        } catch (UnknownHostException e) {
            throw new MqMessageSendException("发送登录日志失败");
        }

        // 返回用户信息
        UserVO userVO = BeanUtils.copyBean(user, UserVO.class);
        userVO.setToken(token);
        userVO.setRoleCode(permissionClient.getUserRoleCode(user.getId()));
        return userVO;
    }


    @Override
    public PageResult<UserVO> getUsers(Integer page, Integer pageSize) {
        if(page == 0 || pageSize == 0) {
            throw new BadRequestException("分页参数不能为0");
        }

        // 当前登录用户
        Long currentUserId = BaseContext.getCurrentId();
        String currentRole = permissionClient.getUserRoleCode(currentUserId);

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //根据用户权限选择查询情况
        switch (currentRole) {
            case PermissionConstans.SUPER_ADMIN:
                // 超管查所有
                break;

            case PermissionConstans.ADMIN:
                // 管理员查普通用户
                List<Long> userIds = permissionClient.getUserIdsByRolesCode(PermissionConstans.USER);
                userIds.add(currentUserId);//添加自己(因为自己也是管理员)
                if (!userIds.isEmpty()) {
                    wrapper.in(User::getId, userIds);
                } else {
                    // 没有普通用户可查，返回空分页
                    return new PageResult<>(0L, Collections.emptyList(), page, pageSize);
                }
                break;

            case PermissionConstans.USER:
            default:
                // 普通用户只看自己
                wrapper.eq(User::getId, currentUserId);
                break;
        }

        //将po转化成vo
        Page<User> pageObj = new Page<>(page, pageSize);
        this.page(pageObj, wrapper);
        List<Long> userIds = pageObj.getRecords().stream().map(User::getId).collect(Collectors.toList());

        //获取用户的角色
        List<UserRoleDTO> userRoleDTOList = permissionClient.getUserRoleByUserIds(userIds);
        Map<Long, String> roleMap = userRoleDTOList.stream().collect(Collectors.toMap(UserRoleDTO::getUserId, UserRoleDTO::getRoleCode));

        List<UserVO> voList = pageObj.getRecords().stream().map(user -> {
            UserVO vo = new UserVO();
            vo.setId(user.getId());
            vo.setUsername(user.getUsername());
            vo.setEmail(user.getEmail());
            vo.setPhone(user.getPhone());
            vo.setRoleCode(roleMap.getOrDefault(user.getId(), "unknown"));
            return vo;
        }).collect(Collectors.toList());

        return new PageResult<>(
                pageObj.getTotal(),
                voList,
                (int) pageObj.getCurrent(),
                (int) pageObj.getSize()
        );
    }


    @Override
    public UserVO getUserById(Long userId) {
        //获取当前用户id
        Long currentUserId = BaseContext.getCurrentId();

        //将user封装成vo
        User user = this.lambdaQuery().eq(User::getId, userId).one();
        if(user == null){
            throw new UserNotExitsException("用户不存在");
        }
        UserVO userVO = BeanUtils.copyBean(user, UserVO.class);
        userVO.setRoleCode(permissionClient.getUserRoleCode(userId));
        //判断查询的是否是自己
        if(currentUserId.equals(userId)) {
            //是自己就直接返回
            return userVO;
        }

        //对用户进行权限校验
        String userRoleCode = permissionClient.getUserRoleCode(currentUserId);
        String curUserRoleCode = permissionClient.getUserRoleCode(userId);
        switch (userRoleCode) {
            //管理员能查询所有普通用户信息
            case PermissionConstans.ADMIN:
                if(curUserRoleCode.equals(PermissionConstans.USER)) {
                    return userVO;
                }else{
                    throw new PermissionDeniedException("权限不足");
                }
            //普通用户只能查询自己的信息(由于之前已经判断是否是查询自己,所以这里肯定不是查询自己)
            case PermissionConstans.USER:
                throw new PermissionDeniedException("权限不足");
            //超级管理员能查询所有用户
            case PermissionConstans.SUPER_ADMIN:
                return userVO;
            default:
                break;
        }

        return null;
    }

    @Override
    public Boolean upgradeToAdmin(Long userId) {
        //参数校验
        if (userId == null) {
            throw new BadRequestException("用户ID不能为空");
        }
        User user = this.lambdaQuery().eq(User::getId, userId).one();
        if(user == null){
            throw new UserNotExitsException("用户不存在");
        }
        //校验权限
        Long currentId = BaseContext.getCurrentId();
        log.info("当前用户id:{}", currentId);
        String userRoleCode = permissionClient.getUserRoleCode(currentId);
        if (!userRoleCode.equals(PermissionConstans.SUPER_ADMIN)) {
            throw new CommonException("权限不足");
        }

        permissionClient.upgradeToAdmin(userId);
        return true;
    }

    @Override
    public Boolean downgradeToUser(Long userId) {
        //参数校验
        if (userId == null) {
            throw new BadRequestException("用户ID不能为空");
        }
        User user = this.lambdaQuery().eq(User::getId, userId).one();
        if(user == null){
            throw new UserNotExitsException("用户不存在");
        }
        //校验权限(本来我认为权限校验应该在permission模块的,但是demo要求是在这里进行校验)
        Long currentId = BaseContext.getCurrentId();
        log.info("当前用户id:{}", currentId);
        String userRoleCode = permissionClient.getUserRoleCode(currentId);
        if (!userRoleCode.equals(PermissionConstans.SUPER_ADMIN)) {
            throw new CommonException("权限不足");
        }

        permissionClient.downgradeToUser(userId);
        return true;
    }

    @Override
    @Transactional
    public Boolean updateUserById(User user) {
        if(user.getId() == null){
            throw new BadRequestException("用户id不能为空");
        }

        // 确保用户存在
        User oldUser = this.getById(user.getId());
        if (oldUser == null) {
            throw new UserNotExitsException("用户不存在");
        }

        //判断是否修改自己
        Long currentId = BaseContext.getCurrentId();
        if(!currentId.equals(user.getId())){
            //校验权限
            String userRoleCode = permissionClient.getUserRoleCode(user.getId());
            String currentRoleCode = permissionClient.getUserRoleCode(currentId);
            switch (currentRoleCode){
                case PermissionConstans.SUPER_ADMIN:
                    break;
                case PermissionConstans.ADMIN:
                    if(!userRoleCode.equals(PermissionConstans.USER)){
                        throw new PermissionDeniedException("权限不足");
                    }
                    break;
                default:
                    throw new PermissionDeniedException("权限不足");
            }
        }


        //更新用户信息
        this.lambdaUpdate()
                .eq(User::getId, user.getId())
                .set(!StringUtils.isBlank(user.getUsername()), User::getUsername, user.getUsername())
                .set(!StringUtils.isBlank(user.getPhone()), User::getPhone, user.getPhone())
                .set(!StringUtils.isBlank(user.getEmail()), User::getEmail, user.getEmail())
                .set(!StringUtils.isBlank(user.getPassword()), User::getPassword, user.getPassword())
                .update();

        //向mq中发送信息
        try {
            // 发送操作日志
            OperationLogs logs = new OperationLogs();
            logs.setUserId(user.getId());
            logs.setAction(LogConstants.USER_UPDATE);
            logs.setIp(InetAddress.getLocalHost().getHostAddress());
            String details = OperationLogDetailUtils.generateUpdateLog(oldUser, user);
            logs.setDetail("用户更新信息:" + details);
            rabbitMqHelper.sendMessage(MqConstants.Exchange.SOFA_LOG_EXCHANGE, MqConstants.RoutingKey.SOFA_LOG_OPERATION, logs);
        } catch (Exception e) {
            throw new CommonException("发送日志信息错误: " + e.getMessage());
        }
        return true;
    }


    @Override
    @Transactional
    public Boolean resetPassword(Long userId) {
        if(userId == null){
            throw new BadRequestException("userId不能为空");
        }

        // 确保用户存在
        User oldUser = this.getById(userId);
        log.info("用户信息:{}", oldUser);
        if (oldUser == null) {
            throw new UserNotExitsException("用户不存在");
        }

        //判断是否修改自己
        Long currentId = BaseContext.getCurrentId();
        if(!currentId.equals(userId)){
            //校验权限
            String userRoleCode = permissionClient.getUserRoleCode(userId);
//            log.info("用户角色:{}", userRoleCode);
            String currentRoleCode = permissionClient.getUserRoleCode(currentId);
//            log.info("当前用户角色是:( {} )", currentRoleCode);
            switch (currentRoleCode){
                case PermissionConstans.SUPER_ADMIN:
                    break;
                case PermissionConstans.ADMIN:
                    if(!userRoleCode.equals(PermissionConstans.USER)){
                        throw new PermissionDeniedException("权限不足");
                    }
                    break;
                default:
                    throw new PermissionDeniedException("权限不足");
            }
        }
        this.lambdaUpdate()
                .eq(User::getId, userId)
                .set(User::getPassword, PasswordConstants.DEFAULT_PASSWORD)
                .update();

        //向mq中发送信息
        try {
            // 发送操作日志
            OperationLogs logs = new OperationLogs();
            logs.setUserId(currentId);
            logs.setAction(LogConstants.RESET_PASSWORD);
            logs.setIp(InetAddress.getLocalHost().getHostAddress());
            String details = OperationLogDetailUtils.generateUpdateLog(oldUser, new User().setPassword(PasswordConstants.DEFAULT_PASSWORD));
            logs.setDetail("重置用户" + userId +"的密码:" + details);
            rabbitMqHelper.sendMessage(MqConstants.Exchange.SOFA_LOG_EXCHANGE, MqConstants.RoutingKey.SOFA_LOG_OPERATION, logs);
        } catch (Exception e) {
            throw new CommonException("发送日志信息错误: " + e.getMessage());
        }
        return true;
    }


}
